/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.web.core.syntax; import java.util.Arrays; import java.util.ArrayList; import org.netbeans.editor.ext.JavaSyntax; import org.netbeans.editor.ext.HTMLSyntax; import org.netbeans.editor.Syntax; /** * Syntax for JSP files. This is a MultiSyntax consisting of three slave syntaxes: host syntax * (for now this is HTMLSyntax), JspTagSyntax and JavaSyntax. * * @author Petr Jiricka * @version 1.00 */ public class JspMultiSyntax extends BaseMultiSyntax { // prefixes for changed names of tokens public static final String HTML_PREFIX = "html-"; public static final String JAVA_PREFIX = "java-"; // modes of nesting of languages public static final int MODE_HOST = 1; public static final int MODE_HOST_JSPTAG = 2; public static final int MODE_HOST_JSPTAG_JAVA = 3; public static final int MODE_HOST_JAVA = 4; // constants for result of operation of checking delimiters protected static final int DELIMCHECK_NO = -1; protected static final int DELIMCHECK_PART = -2; // states of this multisyntax private static final int ISI_LANGUAGE = 1; // one syntax is active and working // states for switching from the host language to JSP tag or Java private static final int ISI_HOST_JSPTAG = 2; // just before <jsptag or similar (recognized by JspTagSyntax) private static final int ISI_HOST_JAVA = 3; // just before <% or similar, after such a delimiter Java block starts, host language private static final int ISI_HOST_JAVA_LT = 4; // as ISI_HOST_JAVA after < private static final int ISI_HOST_JAVA_LT_PC = 5; // as ISI_HOST_JAVA after <% private static final int ISI_HOST_JAVA_JUMP = 6; // after a Java delimiter in host language, now really switch // states for switching from a JSP tag to Java private static final int ISI_JSPTAG_JAVA = 7; // just before <% or similar, after such a delimiter Java block starts, JSPTAG language private static final int ISI_JSPTAG_JAVA_LT = 8; // as ISI_JSPTAG_JAVA after < private static final int ISI_JSPTAG_JAVA_LT_PC = 9; // as ISI_JSPTAG_JAVA after <% private static final int ISI_JSPTAG_JAVA_JUMP = 10; // after a Java delimiter in JSPTAG language, now really switch // states for switching from Java to a JSP tag private static final int ISI_JAVA1_SWITCH = 11; // just before %> in Java (go to JSPTAG) private static final int ISI_JAVA1_PC = 12; // as ISI_JAVA1_SWITCH after % private static final int ISI_JAVA1_JUMP = 13; // after %> in Java, now really switch to JSPTAG // states for switching from Java to host private static final int ISI_JAVA2_SWITCH = 14; // just before %> in Java (go to host) private static final int ISI_JAVA2_PC = 15; // as ISI_JAVA2_SWITCH after % private static final int ISI_JAVA2_JUMP = 16; // after %> in Java, now really switch to host // states of the automaton which looks for delimiters in the host language private static final int HOST_INIT = 1; // initial state - host language private static final int HOST_LT = 2; // after < - host language private static final int HOST_LT_PC = 3; // after <% - host language private static final int HOST_LT_BLANK = 4; // after < or </ and several blanks or \t - host language private static final int HOST_TAG = 5; // inside a tag, don't know whether html or JSP - host language private static final int HOST_LT_SLASH = 6; // after </ - host lanaguage // states of the automaton which looks for delimiters in the JSP tag private static final int JSPTAG_INIT = 1; // initial state - JSP tag private static final int JSPTAG_LT = 2; // after < - JSP tag private static final int JSPTAG_LT_PC = 3; // after <% - JSP tag // states of the automaton which looks for delimiters in Java private static final int JAVA_INIT = 1; // initial state - Java block private static final int JAVA_PC = 2; // after % - Java block protected int nestMode; protected SyntaxInfo hostSyntaxInfo; protected SyntaxInfo jspTagSyntaxInfo; protected SyntaxInfo javaSyntaxInfo; /** When returning from parseToken(), contains the state of the 'host' slave syntax at 'offset'. * Always a part of the StateInfo. */ protected StateInfo hostStateInfo; /** When returning from parseToken(), contains the state of the 'jspTag' slave syntax at 'offset'. * Always a part of the StateInfo. */ protected StateInfo jspTagStateInfo; /** When returning from parseToken(), contains the state of the 'java' slave syntax at 'offset'. * Always a part of the StateInfo. */ protected StateInfo javaStateInfo; // Contains the tokenLenght returned by the first call of nextToken() on the slave syntax. May need to be // stored in the stateinfo if tokenOffset != offset. // If the first call of slave's nextToken() returned EOT, this variable will not be valid, and // the next call must update this variable with the correct value private int firstTokenLength; // Contains the tokenID returned by the first call of nextToken() on the slave syntax. May need to be // stored in the stateinfo if tokenOffset != offset. // If the first call of slave's nextToken() returned EOT, it will be reflected in this variable, and // the next call must update this variable with the correct value private int firstTokenID; // One of the following stateInfos will be a part of the stateInfo, if we are returning EOT. // In such a case it will contain the state of the scanning syntax at 'tokenOffset'. private StateInfo helpHostStateInfo; private StateInfo helpJspTagStateInfo; private StateInfo helpJavaStateInfo; // These stateinfos hold the stateinfo after the first token returned by the scanning stave syntax. // Only when tokenOffset == offset, in the other case need to rescan the first token before returning. private StateInfo firstHostStateInfo; private StateInfo firstJspTagStateInfo; private StateInfo firstJavaStateInfo; private boolean debug = false; public JspMultiSyntax() { hostSyntaxInfo = registerSyntax(new HTMLSyntax()); //hostStateInfo = hostSyntaxInfo.syntax.createStateInfo(); jspTagSyntaxInfo = registerSyntax(new JspTagSyntax()); //jspTagStateInfo = jspTagSyntaxInfo.syntax.createStateInfo(); javaSyntaxInfo = registerSyntax(new JavaSyntax()); //javaStateInfo = javaSyntaxInfo.syntax.createStateInfo(); // private stateinfos firstHostStateInfo = hostSyntaxInfo.syntax.createStateInfo(); firstJspTagStateInfo = jspTagSyntaxInfo.syntax.createStateInfo(); firstJavaStateInfo = javaSyntaxInfo.syntax.createStateInfo(); helpHostStateInfo = hostSyntaxInfo.syntax.createStateInfo(); helpJspTagStateInfo = jspTagSyntaxInfo.syntax.createStateInfo(); helpJavaStateInfo = javaSyntaxInfo.syntax.createStateInfo(); for (int i = 0; i <= javaSyntaxInfo.syntax.getHighestTokenID(); i++) { switch (i) { //case JavaSyntax.TEXT: case JavaSyntax.ERROR: break; default: changeTokenName(javaSyntaxInfo.syntax, i, JAVA_PREFIX + javaSyntaxInfo.syntax.getTokenName(i)); } } if (hostSyntaxInfo.syntax instanceof HTMLSyntax) { for (int i = 0; i <= hostSyntaxInfo.syntax.getHighestTokenID(); i++) { switch (i) { //case HTMLSyntax.TEXT: //case HTMLSyntax.ERROR: // break; default: changeTokenName(hostSyntaxInfo.syntax, i, HTML_PREFIX + hostSyntaxInfo.syntax.getTokenName(i)); } } } // print out token IDs //if (debug) { //for (int i=0; i <= getHighestTokenID(); i++) //System.out.println("token " + (i < 10 ? "0" : "") + i + " " + getTokenName(i)); //} } /** Parses the next token. Before entering this method the following assumptions hold: * <ul> * <li>'Regular' stateinfos contain the state of all active languages at 'offset'. For inactive * languages they are <code>null</code>.</li> * <li>If <code>tokenOffset != offset</code>, the scanning 'help' stateinfo contains the state of the scanning * language at 'tokenOffset'.</li> * <li>If <code>tokenOffset != offset</code>, firstTokenID contains the token returned by the first call of * slave's nextToken() in the current token, may be EOT !</li> * </ul> */ protected int parseToken() { //debug = (tokenOffset != offset); //debug = !((tokenOffset == offset) || (firstTokenID == EOT)); // !firstTokenNotRead //if (debug) //System.out.println("parseToken tokenOffset=" + tokenOffset + ", offset=" + offset + ", state=" + state + //", nestMode=" + nestMode + ", stopOffset=" + stopOffset + ", lastBuffer=" + lastBuffer); if (state != ISI_LANGUAGE) { char actChar; while(offset < stopOffset) { actChar = buffer[offset]; switch (state) { case ISI_HOST_JSPTAG: // switch to JspTagSyntax //if (debug) //System.out.println("switching from HOST to JSPTAG, hostState " + ((BaseStateInfo)hostStateInfo).toString(this)); nestMode = MODE_HOST_JSPTAG; state = ISI_LANGUAGE; transferMasterToSlave(jspTagSyntaxInfo.syntax, null); //jspTagSyntaxInfo.syntax.load(null, buffer, offset, stopOffset - offset, lastBuffer); if (jspTagStateInfo == null) { jspTagStateInfo = jspTagSyntaxInfo.syntax.createStateInfo(); } jspTagSyntaxInfo.syntax.storeState(jspTagStateInfo); break; case ISI_HOST_JAVA: // switch from hostSyntax to JavaSyntax switch (actChar) { case '<': state = ISI_HOST_JAVA_LT; break; default: new Exception("bad hostsyntax analyzer").printStackTrace(); } // switch (actChar) break; case ISI_HOST_JAVA_LT: switch (actChar) { case '%': state = ISI_HOST_JAVA_LT_PC; break; default: new Exception("bad hostsyntax analyzer").printStackTrace(); } // switch (actChar) break; case ISI_HOST_JAVA_LT_PC: switch (actChar) { case '!': // declaration case '=': // expression state = ISI_HOST_JAVA_JUMP; offset++; //if (debug) //System.out.println("returning (1) pos " + offset + " symbol " + getTokenName(JspTagSyntax.JSP_SYMBOL2 + jspTagSyntaxInfo.tokenIDShift)); return JspTagSyntax.JSP_SYMBOL2 + jspTagSyntaxInfo.tokenIDShift; default: // assume this is a scriptlet state = ISI_HOST_JAVA_JUMP; //if (debug) //System.out.println("returning (2) pos " + offset + " symbol " + getTokenName(JspTagSyntax.JSP_SYMBOL2 + jspTagSyntaxInfo.tokenIDShift)); return JspTagSyntax.JSP_SYMBOL2 + jspTagSyntaxInfo.tokenIDShift; } // switch (actChar) // break; - not reached case ISI_HOST_JAVA_JUMP: nestMode = MODE_HOST_JAVA; state = ISI_LANGUAGE; transferMasterToSlave(javaSyntaxInfo.syntax, null); //javaSyntaxInfo.syntax.load(null, buffer, offset, stopOffset - offset, lastBuffer); if (javaStateInfo == null) { javaStateInfo = javaSyntaxInfo.syntax.createStateInfo(); } javaSyntaxInfo.syntax.storeState(javaStateInfo); break; case ISI_JSPTAG_JAVA: // switch from JSP tag to JavaSyntax switch (actChar) { case '<': state = ISI_JSPTAG_JAVA_LT; break; default: new Exception("bad hostsyntax analyzer").printStackTrace(); } // switch (actChar) break; case ISI_JSPTAG_JAVA_LT: switch (actChar) { case '%': state = ISI_JSPTAG_JAVA_LT_PC; break; default: new Exception("bad hostsyntax analyzer").printStackTrace(); } // switch (actChar) break; case ISI_JSPTAG_JAVA_LT_PC: switch (actChar) { case '!': // declaration case '=': // expression state = ISI_JSPTAG_JAVA_JUMP; offset++; //if (debug) //System.out.println("returning (1x) pos " + offset + " symbol " + getTokenName(JspTagSyntax.JSP_SYMBOL2 + jspTagSyntaxInfo.tokenIDShift)); return JspTagSyntax.JSP_SYMBOL2 + jspTagSyntaxInfo.tokenIDShift; default: // assume this is a scriptlet state = ISI_JSPTAG_JAVA_JUMP; //if (debug) //System.out.println("returning (2x) pos " + offset + " symbol " + getTokenName(JspTagSyntax.JSP_SYMBOL2 + jspTagSyntaxInfo.tokenIDShift)); return JspTagSyntax.JSP_SYMBOL2 + jspTagSyntaxInfo.tokenIDShift; } // switch (actChar) // break; - not reached case ISI_JSPTAG_JAVA_JUMP: nestMode = MODE_HOST_JSPTAG_JAVA; state = ISI_LANGUAGE; transferMasterToSlave(javaSyntaxInfo.syntax, null); //javaSyntaxInfo.syntax.load(null, buffer, offset, stopOffset - offset, lastBuffer); if (javaStateInfo == null) { javaStateInfo = javaSyntaxInfo.syntax.createStateInfo(); } javaSyntaxInfo.syntax.storeState(javaStateInfo); break; // switching from Java back to JSPTAG case ISI_JAVA1_SWITCH: switch (actChar) { case '%': state = ISI_JAVA1_PC; break; default: new Exception("bad hostsyntax analyzer").printStackTrace(); } // switch (actChar) break; case ISI_JAVA1_PC: switch (actChar) { case '>': state = ISI_JAVA1_JUMP; offset++; //if (debug) //System.out.println("returning (1xx) pos " + offset + " symbol " + getTokenName(JspTagSyntax.JSP_SYMBOL2 + jspTagSyntaxInfo.tokenIDShift)); return JspTagSyntax.JSP_SYMBOL2 + jspTagSyntaxInfo.tokenIDShift; default: new Exception("bad hostsyntax analyzer").printStackTrace(); } case ISI_JAVA1_JUMP: nestMode = MODE_HOST_JSPTAG; jspTagStateInfo.setPreScan(0); state = ISI_LANGUAGE; javaStateInfo = null; break; // switching from Java back to host case ISI_JAVA2_SWITCH: switch (actChar) { case '%': state = ISI_JAVA2_PC; break; default: new Exception("bad hostsyntax analyzer").printStackTrace(); } // switch (actChar) break; case ISI_JAVA2_PC: switch (actChar) { case '>': state = ISI_JAVA2_JUMP; offset++; //if (debug) //System.out.println("returning (2xx) pos " + offset + " symbol " + getTokenName(JspTagSyntax.JSP_SYMBOL2 + jspTagSyntaxInfo.tokenIDShift)); return JspTagSyntax.JSP_SYMBOL2 + jspTagSyntaxInfo.tokenIDShift; default: new Exception("bad hostsyntax analyzer").printStackTrace(); } case ISI_JAVA2_JUMP: nestMode = MODE_HOST; hostStateInfo.setPreScan(0); state = ISI_LANGUAGE; javaStateInfo = null; break; } if (state == ISI_LANGUAGE) break; offset = ++offset; } // end of while(offset...) if (state != ISI_LANGUAGE) { /** At this stage there's no more text in the scanned buffer. * Scanner first checks whether this is completely the last * available buffer. */ if (lastBuffer) { switch(state) { case ISI_HOST_JSPTAG: case ISI_HOST_JAVA: case ISI_HOST_JAVA_LT: case ISI_HOST_JAVA_LT_PC: case ISI_HOST_JAVA_JUMP: case ISI_JSPTAG_JAVA: case ISI_JSPTAG_JAVA_LT: case ISI_JSPTAG_JAVA_LT_PC: case ISI_JSPTAG_JAVA_JUMP: case ISI_JAVA1_SWITCH: case ISI_JAVA1_PC: case ISI_JAVA1_JUMP: case ISI_JAVA2_SWITCH: case ISI_JAVA2_PC: case ISI_JAVA2_JUMP: //if (debug) //System.out.println("returning (3) pos " + offset + " symbol " + getTokenName(JspTagSyntax.JSP_SYMBOL2 + jspTagSyntaxInfo.tokenIDShift)); return JspTagSyntax.JSP_SYMBOL2 + jspTagSyntaxInfo.tokenIDShift; } // switch (state) } // if lastBuffer //if (debug) //System.out.println("returning (4) pos " + offset + " symbol " + getTokenName(EOT)); return EOT; } // if state != ISI_LANGUAGE - inner } // if state != ISI_LANGUAGE - outer // now state is ISI_LANGUAGE //if (state != ISI_LANGUAGE) new Exception("state should be ISI_LANGUAGE").printStackTrace(); int slaveTokenID = INVALID; int returnedTokenID; int slaveOffset; int canBe; boolean firstTokenNotRead = ((tokenOffset == offset) || (firstTokenID == EOT)); boolean equalPositions = (tokenOffset == offset); switch (nestMode) { // BIG BRANCH - we are in the HOST mode case MODE_HOST: if (hostStateInfo == null) { hostStateInfo = hostSyntaxInfo.syntax.createStateInfo(); hostSyntaxInfo.syntax.reset(); hostSyntaxInfo.syntax.storeState(hostStateInfo); } /*if (debug) { System.out.print("NOT EQUAL tokenOffset=" + tokenOffset + ", offset=" + offset + ", tokenPart='"); for (int i = tokenOffset; i<offset;i++) System.out.print(buffer[i]); System.out.println("', firstTokenID=" + firstTokenID + ", firstTokenLength=" + firstTokenLength); System.out.println("hoststate " + hostStateInfo.getState() + ", prescan=" + hostStateInfo.getPreScan()); System.out.println("helpstate " + helpHostStateInfo.getState() + ", prescan=" + helpHostStateInfo.getPreScan()); } */ //if (equalPositions && (hostStateInfo.getPreScan() != 0)) //new Exception("prescan should be 0 !!").printStackTrace(); //if (debug) //System.out.println("html state at offset " + ((BaseStateInfo)hostStateInfo).toString(this)); if (firstTokenNotRead) { // the first step - parse the first token of the slave transferMasterToSlave(hostSyntaxInfo.syntax, hostStateInfo); returnedTokenID = hostSyntaxInfo.syntax.nextToken(); slaveTokenID = returnedTokenID <= EOL ? returnedTokenID : returnedTokenID + hostSyntaxInfo.tokenIDShift; slaveOffset = hostSyntaxInfo.syntax.getOffset(); firstTokenID = slaveTokenID; firstTokenLength = hostSyntaxInfo.syntax.getTokenLength(); if (slaveTokenID == EOT) { offset = slaveOffset; firstTokenLength = -1; // need to property transfer states if (equalPositions) { helpHostStateInfo = hostStateInfo; hostStateInfo = hostSyntaxInfo.syntax.createStateInfo(); hostSyntaxInfo.syntax.storeState(hostStateInfo); } else { if (hostStateInfo == null) { hostStateInfo = hostSyntaxInfo.syntax.createStateInfo(); } hostSyntaxInfo.syntax.storeState(hostStateInfo); new Exception("returning EOT twice in a row !!!!!!!").printStackTrace(); } //if (debug) //System.out.println("returnuju (1) " + EOT + " at " + offset); return EOT; } // find out if the token could contain a starting symbol for JspTag or Java canBe = canBeHostDelimiter(tokenOffset, slaveOffset, slaveOffset, false); if (canBe == DELIMCHECK_NO) { // do not switch offset = slaveOffset; if (hostStateInfo == null) { hostStateInfo = hostSyntaxInfo.syntax.createStateInfo(); } hostSyntaxInfo.syntax.storeState(hostStateInfo); //if (debug) //System.out.println("returnuju (2) " + slaveTokenID + " at " + offset); return slaveTokenID; } // store the state hostSyntaxInfo.syntax.storeState(firstHostStateInfo); //if (firstHostStateInfo == hostStateInfo) //new Exception("stateinfo instance conflict").printStackTrace(); } else { // first position read - offsets different and firstTokenID is a valid token transferMasterToSlave(hostSyntaxInfo.syntax, hostStateInfo); canBe = DELIMCHECK_PART; } // we have successfully read the first token, the following statements hold: // - canBe is not DELIMCHECK_NO // - firstTokenID and firstTokenLength are meaningful // - if (equalPositions) then firstHostStateInfo is meaningful //if (firstTokenID == EOT) { //new Exception("invalid firstTokenID !!!!!!!").printStackTrace(); //} while (canBe == DELIMCHECK_PART) { // need another token // now get the new token returnedTokenID = hostSyntaxInfo.syntax.nextToken(); slaveTokenID = returnedTokenID <= EOL ? returnedTokenID : returnedTokenID + hostSyntaxInfo.tokenIDShift; slaveOffset = hostSyntaxInfo.syntax.getOffset(); if ((slaveTokenID == EOT) && lastBuffer) { // ask about the delimiter, but with lastPart=true canBe = canBeHostDelimiter(tokenOffset, slaveOffset, tokenOffset + firstTokenLength, true); if (canBe != DELIMCHECK_PART) break; } if (slaveTokenID == EOT) { if (lastBuffer) { canBe = DELIMCHECK_NO; break; } offset = slaveOffset; if (equalPositions) { helpHostStateInfo = hostStateInfo; hostStateInfo = hostSyntaxInfo.syntax.createStateInfo(); hostSyntaxInfo.syntax.storeState(hostStateInfo); } else { if (hostStateInfo == null) { hostStateInfo = hostSyntaxInfo.syntax.createStateInfo(); } hostSyntaxInfo.syntax.storeState(hostStateInfo); //new Exception("returning EOT twice in a row !!!!!!!").printStackTrace(); } //if (debug) //System.out.println("returnuju (3) " + EOT + " at " + offset); return EOT; } canBe = canBeHostDelimiter(tokenOffset, slaveOffset, tokenOffset + firstTokenLength, false); } // now canBe is not DELIMCHECK_PART // now we have read possibly more tokens and know whether to switch or not if (canBe == DELIMCHECK_NO) { // do not switch offset = tokenOffset + firstTokenLength; if (equalPositions) { hostStateInfo = firstHostStateInfo; firstHostStateInfo = hostSyntaxInfo.syntax.createStateInfo(); } else { //if (debug) //System.out.println("= imagine - rescan called !!"); //if (helpHostStateInfo.getPreScan() != 0) //new Exception("help prescan should be 0 !!").printStackTrace(); // we need to rescan the first token to find out the state // now helpHostStateInfo is useful hostSyntaxInfo.syntax.load(helpHostStateInfo, buffer, tokenOffset, stopOffset - tokenOffset, lastBuffer); returnedTokenID = hostSyntaxInfo.syntax.nextToken(); //if (tokenOffset != hostSyntaxInfo.syntax.getTokenOffset()) //new Exception("starts of tokens do not match").printStackTrace(); slaveTokenID = returnedTokenID <= EOL ? returnedTokenID : returnedTokenID + hostSyntaxInfo.tokenIDShift; if (hostStateInfo == null) { hostStateInfo = hostSyntaxInfo.syntax.createStateInfo(); } hostSyntaxInfo.syntax.storeState(hostStateInfo); //if (slaveTokenID != firstTokenID) //new Exception("token ID does not match !!!!!!!").printStackTrace(); //if (offset != hostSyntaxInfo.syntax.getOffset()) //new Exception("offset does not match !!!!!!!").printStackTrace(); /*if (debug) System.out.println("delimiter NO, equalPositions=false, firstTokenNotRead=" + firstTokenNotRead + ", tokenOffset=" + tokenOffset + ", offset=" + offset + ", slave offset=" + hostSyntaxInfo.syntax.getOffset() + ", token='" + getToken(hostSyntaxInfo.syntax) +"', tokenID=" + slaveTokenID + ", firstTokenID=" + firstTokenID);*/ } //if (debug) //System.out.println("returnuju (4) " + firstTokenID + " at " + offset); return firstTokenID; } else { // we found a delimiter //if (canBe >= tokenOffset + firstTokenLength) //new Exception("value of canBe is invalid !!!!!!!").printStackTrace(); // now use the saved state if (equalPositions) { hostSyntaxInfo.syntax.load(hostStateInfo, buffer, tokenOffset, canBe - tokenOffset, true); } else { hostSyntaxInfo.syntax.load(helpHostStateInfo, buffer, tokenOffset, canBe - tokenOffset, true); } returnedTokenID = hostSyntaxInfo.syntax.nextToken(); // we got the StateInfo, which is why we did all this if (hostStateInfo == null) { hostStateInfo = hostSyntaxInfo.syntax.createStateInfo(); } //if (debug) //System.out.println("html state before saving back " + ((BaseStateInfo)hostStateInfo).toString(this)); hostSyntaxInfo.syntax.storeState(hostStateInfo); hostStateInfo.setPreScan(0); //if (hostSyntaxInfo.syntax.getOffset() != canBe) //new Exception("bad number of characters parsed !!!").printStackTrace(); offset = canBe; /*if (debug) { System.out.println("switching from HOST to JSPTAG at offset " + offset + ", hostState " + ((BaseStateInfo)hostStateInfo).toString(this)); System.out.println("offset of the returned (a)" + hostSyntaxInfo.syntax.getOffset()); System.out.println("found delimiter at " + offset); System.out.println("returnuju (5) " + firstTokenID + " at " + offset); }*/ return firstTokenID; } //break; //- not reached // BIG BRANCH - we are in the HOST_JSPTAG mode case MODE_HOST_JSPTAG: // check if the JSP tag hasn't finished on its own will if ((jspTagStateInfo != null) && (jspTagStateInfo.getState() == JspTagSyntax.ISA_END_JSP)) { // give up control jspTagStateInfo = null; nestMode = MODE_HOST; hostStateInfo.setPreScan(0); /*if (debug) { System.out.println("switching back to HOST from JSPTAG at offset " + offset + ", hostState " + ((BaseStateInfo)hostStateInfo).toString(this)); System.out.println("returnuju (6) " + JspTagSyntax.TEXT + jspTagSyntaxInfo.tokenIDShift + " at " + offset); }*/ return JspTagSyntax.TEXT + jspTagSyntaxInfo.tokenIDShift; } if (jspTagStateInfo == null) { jspTagStateInfo = jspTagSyntaxInfo.syntax.createStateInfo(); jspTagSyntaxInfo.syntax.reset(); jspTagSyntaxInfo.syntax.storeState(jspTagStateInfo); } if (firstTokenNotRead) { // the first step - parse the first token of the slave transferMasterToSlave(jspTagSyntaxInfo.syntax, jspTagStateInfo); returnedTokenID = jspTagSyntaxInfo.syntax.nextToken(); slaveTokenID = returnedTokenID <= EOL ? returnedTokenID : returnedTokenID + jspTagSyntaxInfo.tokenIDShift; //if (debug) //System.out.println("first JSPtoken returned '" + getToken(jspTagSyntaxInfo.syntax) + "' id " + slaveTokenID); slaveOffset = jspTagSyntaxInfo.syntax.getOffset(); firstTokenID = slaveTokenID; firstTokenLength = jspTagSyntaxInfo.syntax.getTokenLength(); if (slaveTokenID == EOT) { offset = slaveOffset; firstTokenLength = -1; // need to properly transfer states if (equalPositions) { helpJspTagStateInfo = jspTagStateInfo; jspTagStateInfo = jspTagSyntaxInfo.syntax.createStateInfo(); jspTagSyntaxInfo.syntax.storeState(jspTagStateInfo); } else { if (jspTagStateInfo == null) { jspTagStateInfo = jspTagSyntaxInfo.syntax.createStateInfo(); } jspTagSyntaxInfo.syntax.storeState(jspTagStateInfo); //new Exception("returning EOT twice in a row !!!!!!!").printStackTrace(); } //if (debug) //System.out.println("returnuju (7) " + EOT + " at " + offset); return EOT; } // find out if the token could contain a starting symbol for Java canBe = canBeJspTagDelimiter(tokenOffset, slaveOffset, slaveOffset, false, returnedTokenID == JspTagSyntax.JSP_COMMENT); if (canBe == DELIMCHECK_NO) { // do not switch offset = slaveOffset; if (jspTagStateInfo == null) { jspTagStateInfo = jspTagSyntaxInfo.syntax.createStateInfo(); } jspTagSyntaxInfo.syntax.storeState(jspTagStateInfo); //if (debug) //System.out.println("returnuju (8) " + slaveTokenID + " at " + offset); return slaveTokenID; } // store the state jspTagSyntaxInfo.syntax.storeState(firstJspTagStateInfo); } else { // first position read - offsets different and firstTokenID is a valid token transferMasterToSlave(jspTagSyntaxInfo.syntax, jspTagStateInfo); canBe = DELIMCHECK_PART; } // we have successfully read the first token, the following statements hold: // - canBe is not DELIMCHECK_NO // - firstTokenID and firstTokenLength are meaningful // - if (equalPositions) then firstJspTagStateInfo is meaningful //if (firstTokenID == EOT) { //new Exception("invalid firstTokenID !!!!!!!").printStackTrace(); //} while (canBe == DELIMCHECK_PART) { // need another token // now get the new token returnedTokenID = jspTagSyntaxInfo.syntax.nextToken(); slaveTokenID = returnedTokenID <= EOL ? returnedTokenID : returnedTokenID + jspTagSyntaxInfo.tokenIDShift; slaveOffset = jspTagSyntaxInfo.syntax.getOffset(); if ((slaveTokenID == EOT) && lastBuffer) { // ask about the delimiter, but with lastPart=true canBe = canBeJspTagDelimiter(tokenOffset, slaveOffset, tokenOffset + firstTokenLength, true, returnedTokenID == JspTagSyntax.JSP_COMMENT); if (canBe != DELIMCHECK_PART) break; } if (slaveTokenID == EOT) { if (lastBuffer) { canBe = DELIMCHECK_NO; break; } offset = slaveOffset; if (equalPositions) { helpJspTagStateInfo = jspTagStateInfo; jspTagStateInfo = jspTagSyntaxInfo.syntax.createStateInfo(); jspTagSyntaxInfo.syntax.storeState(jspTagStateInfo); } else { if (jspTagStateInfo == null) { jspTagStateInfo = jspTagSyntaxInfo.syntax.createStateInfo(); } jspTagSyntaxInfo.syntax.storeState(jspTagStateInfo); //new Exception("returning EOT twice in a row !!!!!!!").printStackTrace(); } //if (debug) //System.out.println("returnuju (9) " + EOT + " at " + offset); return EOT; } canBe = canBeJspTagDelimiter(tokenOffset, slaveOffset, tokenOffset + firstTokenLength, false, returnedTokenID == JspTagSyntax.JSP_COMMENT); } // now canBe is not DELIMCHECK_PART // now we have read possibly more tokens and know whether to switch or not if (canBe == DELIMCHECK_NO) { // do not switch offset = tokenOffset + firstTokenLength; if (equalPositions) { jspTagStateInfo = firstJspTagStateInfo; firstJspTagStateInfo = jspTagSyntaxInfo.syntax.createStateInfo(); } else { //if (debug) //System.out.println("= imagine - rescan called !!"); // we need to rescan the first token to find out the state // now helpJspTagStateInfo is useful jspTagSyntaxInfo.syntax.load(helpJspTagStateInfo, buffer, tokenOffset, stopOffset - tokenOffset, lastBuffer); returnedTokenID = jspTagSyntaxInfo.syntax.nextToken(); slaveTokenID = returnedTokenID <= EOL ? returnedTokenID : returnedTokenID + jspTagSyntaxInfo.tokenIDShift; if (jspTagStateInfo == null) { jspTagStateInfo = jspTagSyntaxInfo.syntax.createStateInfo(); } jspTagSyntaxInfo.syntax.storeState(jspTagStateInfo); //if (slaveTokenID != firstTokenID) //new Exception("token ID does not match !!!!!!!").printStackTrace(); //if (offset != jspTagSyntaxInfo.syntax.getOffset()) //new Exception("offset does not match !!!!!!!").printStackTrace(); } //if (debug) //System.out.println("returnuju (10) " + firstTokenID + " at " + offset); return firstTokenID; } else { // we found a delimiter //if (canBe >= tokenOffset + firstTokenLength) //new Exception("value of canBe is invalid !!!!!!!").printStackTrace(); // now use the saved state if (equalPositions) { jspTagSyntaxInfo.syntax.load(jspTagStateInfo, buffer, tokenOffset, canBe - tokenOffset, true); } else { jspTagSyntaxInfo.syntax.load(helpJspTagStateInfo, buffer, tokenOffset, canBe - tokenOffset, true); } returnedTokenID = jspTagSyntaxInfo.syntax.nextToken(); // we got the StateInfo, which is why we did all this if (jspTagStateInfo == null) { jspTagStateInfo = jspTagSyntaxInfo.syntax.createStateInfo(); } jspTagSyntaxInfo.syntax.storeState(jspTagStateInfo); jspTagStateInfo.setPreScan(0); //if (jspTagSyntaxInfo.syntax.getOffset() != canBe) //new Exception("bad number of characters parsed !!!").printStackTrace(); offset = canBe; /*if (debug) { System.out.println("offset of the returned (a)" + jspTagSyntaxInfo.syntax.getOffset()); System.out.println("found delimiter at " + offset); System.out.println("returnuju (11) " + firstTokenID + " at " + offset); }*/ return firstTokenID; } //break; //- not reached case MODE_HOST_JSPTAG_JAVA: case MODE_HOST_JAVA: if (javaStateInfo == null) { javaStateInfo = javaSyntaxInfo.syntax.createStateInfo(); javaSyntaxInfo.syntax.reset(); javaSyntaxInfo.syntax.storeState(javaStateInfo); } if (firstTokenNotRead) { // the first step - parse the first token of the slave transferMasterToSlave(javaSyntaxInfo.syntax, javaStateInfo); returnedTokenID = javaSyntaxInfo.syntax.nextToken(); slaveTokenID = returnedTokenID <= EOL ? returnedTokenID : returnedTokenID + javaSyntaxInfo.tokenIDShift; slaveOffset = javaSyntaxInfo.syntax.getOffset(); firstTokenID = slaveTokenID; firstTokenLength = javaSyntaxInfo.syntax.getTokenLength(); if (slaveTokenID == EOT) { offset = slaveOffset; firstTokenLength = -1; // need to property transfer states if (equalPositions) { helpJavaStateInfo = javaStateInfo; javaStateInfo = javaSyntaxInfo.syntax.createStateInfo(); javaSyntaxInfo.syntax.storeState(javaStateInfo); } else { if (javaStateInfo == null) { javaStateInfo = javaSyntaxInfo.syntax.createStateInfo(); } javaSyntaxInfo.syntax.storeState(javaStateInfo); //new Exception("returning EOT twice in a row !!!!!!!").printStackTrace(); } //if (debug) //System.out.println("returnuju (12) " + EOT + " at " + offset); return EOT; } // find out if the token could contain an ending symbol for a Java block canBe = canBeJavaDelimiter(tokenOffset, slaveOffset, slaveOffset, false, nestMode); if (canBe == DELIMCHECK_NO) { // do not switch offset = slaveOffset; if (javaStateInfo == null) { javaStateInfo = javaSyntaxInfo.syntax.createStateInfo(); } javaSyntaxInfo.syntax.storeState(javaStateInfo); //if (debug) //System.out.println("returnuju (13) " + slaveTokenID + " at " + offset); return slaveTokenID; } // store the state javaSyntaxInfo.syntax.storeState(firstJavaStateInfo); } else { // first position read - offsets different and firstTokenID is a valid token transferMasterToSlave(javaSyntaxInfo.syntax, javaStateInfo); canBe = DELIMCHECK_PART; } // we have successfully read the first token, the following statements hold: // - canBe is not DELIMCHECK_NO // - firstTokenID and firstTokenLength are meaningful // - if (equalPositions) then firstJavaStateInfo is meaningful //if (firstTokenID == EOT) { //new Exception("invalid firstTokenID !!!!!!!").printStackTrace(); //} while (canBe == DELIMCHECK_PART) { // need another token // now get the new token returnedTokenID = javaSyntaxInfo.syntax.nextToken(); slaveTokenID = returnedTokenID <= EOL ? returnedTokenID : returnedTokenID + javaSyntaxInfo.tokenIDShift; slaveOffset = javaSyntaxInfo.syntax.getOffset(); if ((slaveTokenID == EOT) && lastBuffer) { // ask about the delimiter, but with lastPart=true canBe = canBeJavaDelimiter(tokenOffset, slaveOffset, tokenOffset + firstTokenLength, true, nestMode); if (canBe != DELIMCHECK_PART) break; } if (slaveTokenID == EOT) { if (lastBuffer) { canBe = DELIMCHECK_NO; break; } offset = slaveOffset; if (equalPositions) { helpJavaStateInfo = javaStateInfo; javaStateInfo = javaSyntaxInfo.syntax.createStateInfo(); javaSyntaxInfo.syntax.storeState(javaStateInfo); } else { if (javaStateInfo == null) { javaStateInfo = javaSyntaxInfo.syntax.createStateInfo(); } javaSyntaxInfo.syntax.storeState(javaStateInfo); //new Exception("returning EOT twice in a row !!!!!!!").printStackTrace(); } //if (debug) //System.out.println("returnuju (14) " + EOT + " at " + offset); return EOT; } canBe = canBeJavaDelimiter(tokenOffset, slaveOffset, tokenOffset + firstTokenLength, false, nestMode); } // now canBe is not DELIMCHECK_PART // now we have read possibly more tokens and know whether to switch or not if (canBe == DELIMCHECK_NO) { // do not switch offset = tokenOffset + firstTokenLength; if (equalPositions) { javaStateInfo = firstJavaStateInfo; firstJavaStateInfo = javaSyntaxInfo.syntax.createStateInfo(); } else { //if (debug) //System.out.println("= imagine - rescan called !!"); // we need to rescan the first token to find out the state // now helpJavaStateInfo is useful javaSyntaxInfo.syntax.load(helpJavaStateInfo, buffer, tokenOffset, stopOffset - tokenOffset, lastBuffer); returnedTokenID = javaSyntaxInfo.syntax.nextToken(); slaveTokenID = returnedTokenID <= EOL ? returnedTokenID : returnedTokenID + javaSyntaxInfo.tokenIDShift; if (javaStateInfo == null) { javaStateInfo = javaSyntaxInfo.syntax.createStateInfo(); } javaSyntaxInfo.syntax.storeState(javaStateInfo); //if (slaveTokenID != firstTokenID) //new Exception("token ID does not match !!!!!!!").printStackTrace(); //if (offset != javaSyntaxInfo.syntax.getOffset()) //new Exception("offset does not match !!!!!!!").printStackTrace(); } //if (debug) //System.out.println("returnuju (15) " + firstTokenID + " at " + offset); return firstTokenID; } else { // we found a delimiter //if (canBe >= tokenOffset + firstTokenLength) //new Exception("value of canBe is invalid !!!!!!!").printStackTrace(); // now use the saved state if (equalPositions) { javaSyntaxInfo.syntax.load(javaStateInfo, buffer, tokenOffset, canBe - tokenOffset, true); } else { javaSyntaxInfo.syntax.load(helpJavaStateInfo, buffer, tokenOffset, canBe - tokenOffset, true); } returnedTokenID = javaSyntaxInfo.syntax.nextToken(); // we got the StateInfo, which is why we did all this if (javaStateInfo == null) { javaStateInfo = javaSyntaxInfo.syntax.createStateInfo(); } javaSyntaxInfo.syntax.storeState(javaStateInfo); javaStateInfo.setPreScan(0); //if (javaSyntaxInfo.syntax.getOffset() != canBe) //new Exception("bad number of characters parsed !!!").printStackTrace(); offset = canBe; /*if (debug) { System.out.println("offset of the returned (a)" + javaSyntaxInfo.syntax.getOffset()); System.out.println("found delimiter at " + offset); System.out.println("returnuju (16) " + firstTokenID + " at " + offset); }*/ return firstTokenID; } // break; //- not reached default: new Exception("bad nestmode").printStackTrace(); return 0; } } /** Method for debugging purposes */ private String getToken(Syntax syntax) { StringBuffer token = new StringBuffer(); for (int i=syntax.getOffset()-syntax.getTokenLength();i<syntax.getOffset();i++) token.append(buffer[i]); return token.toString(); } /** Checks if the part of the buffer starting at tokenOffset and ending just before endOffset * contains a "delimiter" or could contain a starting part of a "delimiter", where * "delimiter" is a lexical structure which could start a JSP tag of a Java block in * the host language, i.e. <code><jsp:useBean</code> or <code><%=</code>. * @return <ul> * <li><code>DELIMCHECK_NO</code> if the part of the buffer does not contain a delimiter or its part</li> * <li><code>DELIMCHECK_PART</code> if the part of the buffer contains part of the delimiter</li> * <li>index of the starting symbol of the delimiter if the part of the buffer contains the delimiter. * In such a case variable <code>state</code> is set properly.</li> * </ul> */ protected int canBeHostDelimiter(int tokenOffset, int endOffset, int firstTokenEnd, boolean lastPart) { int offset = tokenOffset; char actChar; int possibleBeginning = DELIMCHECK_NO; StringBuffer tagString = null; int delimState = HOST_INIT; while(offset < endOffset) { actChar = buffer[offset]; switch (delimState) { case HOST_INIT: switch (actChar) { case '<': if (offset >= firstTokenEnd) return DELIMCHECK_NO; delimState = HOST_LT; possibleBeginning = offset; break; default: if (offset >= firstTokenEnd) return DELIMCHECK_NO; break; } break; case HOST_LT: if ((actChar >= 'A' && actChar <= 'Z') || (actChar >= 'a' && actChar <= 'z') || (actChar == '_') ) { // possible tag begining delimState = HOST_TAG; tagString = new StringBuffer(); tagString.append(actChar); break; // the switch statement } switch (actChar) { case '\n': delimState = HOST_INIT; break; case '%': delimState = HOST_LT_PC; break; case '/': delimState = HOST_LT_SLASH; break; case ' ': case '\t': delimState = HOST_LT_BLANK; break; default: delimState = HOST_INIT; offset--; break; } break; case HOST_LT_SLASH: if ((actChar >= 'A' && actChar <= 'Z') || (actChar >= 'a' && actChar <= 'z') || (actChar == '_') ) { // possible tag begining delimState = HOST_TAG; tagString = new StringBuffer(); tagString.append(actChar); break; // the switch statement } switch (actChar) { case '\n': delimState = HOST_INIT; break; case ' ': case '\t': delimState = HOST_LT_BLANK; break; default: delimState = HOST_INIT; offset--; break; } break; case HOST_LT_BLANK: if ((actChar >= 'A' && actChar <= 'Z') || (actChar >= 'a' && actChar <= 'z') || (actChar == '_') ) { // possible tag begining delimState = HOST_TAG; tagString = new StringBuffer(actChar); break; // the switch statement } switch (actChar) { case '\n': delimState = HOST_INIT; break; case ' ': case '\t': break; default: delimState = HOST_INIT; offset--; break; } break; case HOST_TAG: if ((actChar >= 'A' && actChar <= 'Z') || (actChar >= 'a' && actChar <= 'z') || (actChar >= '0' && actChar <= '9') || (actChar == ':') || (actChar == '_') ) { // the tag continues tagString.append(actChar); break; // the switch statement } switch (actChar) { default: if (isJspTag(tagString.toString())) { state = ISI_HOST_JSPTAG; //if (debug) //System.out.println("found beginning of JspTag at " + possibleBeginning); return possibleBeginning; } else { delimState = HOST_INIT; offset--; break; } } break; case HOST_LT_PC: switch (actChar) { case '@': // directive case '-': // JSP comment state = ISI_HOST_JSPTAG; //if (debug) //System.out.println("found beginning of directive/comment at " + possibleBeginning); return possibleBeginning; case '!': // declaration case '=': // expression state = ISI_HOST_JAVA; //if (debug) //System.out.println("found beginning of declaration/expression at " + possibleBeginning); return possibleBeginning; default: // scriptlet state = ISI_HOST_JAVA; //if (debug) //System.out.println("found beginning of scriptlet at " + possibleBeginning); return possibleBeginning; } //break; } offset++; } if (lastPart) { switch (delimState) { case HOST_LT_PC: state = ISI_HOST_JAVA; return possibleBeginning; case HOST_TAG: if (isJspTag(tagString.toString())) { state = ISI_HOST_JSPTAG; //if (debug) //System.out.println("found beginning of JspTag at " + possibleBeginning); return possibleBeginning; } } } // we have reached the end of the scanned area switch (delimState) { case HOST_INIT: return DELIMCHECK_NO; case HOST_LT: case HOST_LT_SLASH: case HOST_LT_PC: case HOST_LT_BLANK: case HOST_TAG: return DELIMCHECK_PART; default: new Exception("invalid state").printStackTrace(); return DELIMCHECK_NO; } } /** Checks if the part of the buffer starting at tokenOffset and ending just before endOffset * contains a "delimiter" or could contain a starting part of a "delimiter", where * "delimiter" is a lexical structure which could start a Java block inside a JSP tag, * i.e. <code><%=</code>. * @return <ul> * <li><code>DELIMCHECK_NO</code> if the part of the buffer does not contain a delimiter or its part</li> * <li><code>DELIMCHECK_PART</code> if the part of the buffer contains part of the delimiter</li> * <li>index of the starting symbol of the delimiter if the part of the buffer contains the delimiter. * In such a case variable <code>state</code> is set properly.</li> * </ul> */ protected int canBeJspTagDelimiter(int tokenOffset, int endOffset, int firstTokenEnd, boolean lastPart, boolean isComment) { if (isComment) return DELIMCHECK_NO; int offset = tokenOffset; char actChar; int possibleBeginning = DELIMCHECK_NO; int delimState = JSPTAG_INIT; while(offset < endOffset) { actChar = buffer[offset]; switch (delimState) { case JSPTAG_INIT: switch (actChar) { case '<': if (offset >= firstTokenEnd) return DELIMCHECK_NO; delimState = JSPTAG_LT; possibleBeginning = offset; break; default: if (offset >= firstTokenEnd) return DELIMCHECK_NO; break; } break; case JSPTAG_LT: switch (actChar) { case '\n': delimState = JSPTAG_INIT; break; case '%': delimState = JSPTAG_LT_PC; break; default: delimState = JSPTAG_INIT; offset--; break; } break; case JSPTAG_LT_PC: switch (actChar) { case '!': // declaration case '=': // expression state = ISI_JSPTAG_JAVA; //if (debug) //System.out.println("found beginning of declaration/expression at " + possibleBeginning); return possibleBeginning; case '@': // declaration case '-': // comment delimState = JSPTAG_INIT; break; default: // scriptlet state = ISI_JSPTAG_JAVA; //if (debug) //System.out.println("found beginning of scriptlet at " + possibleBeginning); return possibleBeginning; } //break; } offset++; } if (lastPart) { switch (delimState) { case JSPTAG_LT_PC: state = ISI_JSPTAG_JAVA; //if (debug) //System.out.println("found beginning of scriptlet at " + possibleBeginning); return possibleBeginning; } } // we have reached the end of the scanned area switch (delimState) { case JSPTAG_INIT: return DELIMCHECK_NO; case JSPTAG_LT: return DELIMCHECK_PART; case JSPTAG_LT_PC: return DELIMCHECK_PART; default: new Exception("invalid state").printStackTrace(); return DELIMCHECK_NO; } } /** Checks if the part of the buffer starting at tokenOffset and ending just before endOffset * contains a "delimiter" or could contain a starting part of a "delimiter", where * "delimiter" is a lexical structure which could end a Java block, * i.e. <code>%></code>. * @return <ul> * <li><code>DELIMCHECK_NO</code> if the part of the buffer does not contain a delimiter or its part</li> * <li><code>DELIMCHECK_PART</code> if the part of the buffer contains part of the delimiter</li> * <li>index of the starting symbol of the delimiter if the part of the buffer contains the delimiter. * In such a case variable <code>state</code> is set properly.</li> * </ul> */ protected int canBeJavaDelimiter(int tokenOffset, int endOffset, int firstTokenEnd, boolean lastPart, int myNestMode) { int offset = tokenOffset; char actChar; int possibleBeginning = DELIMCHECK_NO; int delimState = JAVA_INIT; while(offset < endOffset) { actChar = buffer[offset]; switch (delimState) { case JAVA_INIT: switch (actChar) { case '%': if (offset >= firstTokenEnd) return DELIMCHECK_NO; delimState = JAVA_PC; possibleBeginning = offset; break; default: if (offset >= firstTokenEnd) return DELIMCHECK_NO; break; } break; case JAVA_PC: switch (actChar) { case '>': switch (myNestMode) { case MODE_HOST_JSPTAG_JAVA: state = ISI_JAVA1_SWITCH; //if (debug) //System.out.println("found end of Java at " + possibleBeginning); return possibleBeginning; case MODE_HOST_JAVA: state = ISI_JAVA2_SWITCH; //if (debug) //System.out.println("found end of Java at " + possibleBeginning); return possibleBeginning; } new Exception("bad nestMode").printStackTrace(); //break; - not reached case '%': if (offset >= firstTokenEnd) return DELIMCHECK_NO; delimState = JAVA_PC; possibleBeginning = offset; break; default: delimState = JAVA_INIT; break; } break; } offset++; } // we have reached the end of the scanned area switch (delimState) { case JAVA_INIT: return DELIMCHECK_NO; case JAVA_PC: return DELIMCHECK_PART; default: new Exception("invalid state").printStackTrace(); return DELIMCHECK_NO; } } /** Determines whether a given string is a JSP tag. */ protected boolean isJspTag(String tagName) { boolean canBeJsp = tagName.startsWith("jsp:"); //if (debug) //System.out.println("can be JSP: '" + tagName + "' " + canBeJsp); return canBeJsp; } private void transferMasterToSlave(Syntax slave, StateInfo stateInfo) { slave.load(stateInfo, buffer, offset, stopOffset - offset, lastBuffer); //slave.setLastBuffer(lastBuffer); // PENDING - maybe not necessary //slave.setStopOffset(stopOffset); // PENDING - maybe not necessary } /** Store state of this analyzer into given mark state. */ public void storeState(StateInfo stateInfo) { super.storeState(stateInfo); JspStateInfo jspsi = (JspStateInfo)stateInfo; // nest mode jspsi.nestMode = nestMode; // regular stateinfos if (hostStateInfo == null) { jspsi.hostStateInfo = null; } else { jspsi.hostStateInfo = hostSyntaxInfo.syntax.createStateInfo(); hostSyntaxInfo.syntax.load(hostStateInfo, buffer, offset, 0, false); hostSyntaxInfo.syntax.storeState(jspsi.hostStateInfo); } if (jspTagStateInfo == null) { jspsi.jspTagStateInfo = null; } else { jspsi.jspTagStateInfo = jspTagSyntaxInfo.syntax.createStateInfo(); jspTagSyntaxInfo.syntax.load(jspTagStateInfo, buffer, offset, 0, false); jspTagSyntaxInfo.syntax.storeState(jspsi.jspTagStateInfo); } if (javaStateInfo == null) { jspsi.javaStateInfo = null; } else { jspsi.javaStateInfo = javaSyntaxInfo.syntax.createStateInfo(); javaSyntaxInfo.syntax.load(javaStateInfo, buffer, offset, 0, false); javaSyntaxInfo.syntax.storeState(jspsi.javaStateInfo); } // stateOfScanningAtInit, firstTokenID, firstTokenLength if (jspsi.isFirstTokenValid()) { jspsi.firstTokenID = firstTokenID; jspsi.firstTokenLength = firstTokenLength; switch (nestMode) { case MODE_HOST: jspsi.stateOfScanningAtInit = hostSyntaxInfo.syntax.createStateInfo(); hostSyntaxInfo.syntax.load(helpHostStateInfo, buffer, offset, 0, false); hostSyntaxInfo.syntax.storeState(jspsi.stateOfScanningAtInit); break; case MODE_HOST_JSPTAG: jspsi.stateOfScanningAtInit = jspTagSyntaxInfo.syntax.createStateInfo(); jspTagSyntaxInfo.syntax.load(helpJspTagStateInfo, buffer, offset, 0, false); jspTagSyntaxInfo.syntax.storeState(jspsi.stateOfScanningAtInit); break; case MODE_HOST_JSPTAG_JAVA: case MODE_HOST_JAVA: jspsi.stateOfScanningAtInit = javaSyntaxInfo.syntax.createStateInfo(); javaSyntaxInfo.syntax.load(helpJavaStateInfo, buffer, offset, 0, false); javaSyntaxInfo.syntax.storeState(jspsi.stateOfScanningAtInit); break; } } else { jspsi.stateOfScanningAtInit = null; jspsi.firstTokenID = EOT; jspsi.firstTokenLength = -1; } /*System.out.print("storing state at offset=" + offset + ", tokenOffset=" + tokenOffset + ", token="); for(int i=tokenOffset;i<offset;i++) System.out.print(buffer[i]); System.out.println(); System.out.println(((JspStateInfo)stateInfo).toString(this));*/ } public void loadState(StateInfo stateInfo) { /*System.out.println("loading state"); System.out.println(((JspStateInfo)stateInfo).toString(this)); */ super.loadState(stateInfo); JspStateInfo jspsi = (JspStateInfo)stateInfo; nestMode = jspsi.nestMode; // now all the slave states if (jspsi.hostStateInfo == null) { hostStateInfo = null; } else { hostSyntaxInfo.syntax.load(jspsi.hostStateInfo, buffer, offset, 0, false); hostStateInfo = hostSyntaxInfo.syntax.createStateInfo(); hostSyntaxInfo.syntax.storeState(hostStateInfo); } if (jspsi.jspTagStateInfo == null) { jspTagStateInfo = null; } else { jspTagSyntaxInfo.syntax.load(jspsi.jspTagStateInfo, buffer, offset, 0, false); jspTagStateInfo = jspTagSyntaxInfo.syntax.createStateInfo(); jspTagSyntaxInfo.syntax.storeState(jspTagStateInfo); } if (jspsi.javaStateInfo == null) { javaStateInfo = null; } else { javaSyntaxInfo.syntax.load(jspsi.javaStateInfo, buffer, offset, 0, false); javaStateInfo = javaSyntaxInfo.syntax.createStateInfo(); javaSyntaxInfo.syntax.storeState(javaStateInfo); } // stateOfScanningAtInit, firstTokenID, firstTokenLength if (jspsi.isFirstTokenValid()) { firstTokenID = jspsi.firstTokenID; firstTokenLength = jspsi.firstTokenLength; switch (jspsi.nestMode) { case MODE_HOST: hostSyntaxInfo.syntax.load(jspsi.stateOfScanningAtInit, buffer, offset, 0, false); hostSyntaxInfo.syntax.storeState(helpHostStateInfo); break; case MODE_HOST_JSPTAG: jspTagSyntaxInfo.syntax.load(jspsi.stateOfScanningAtInit, buffer, offset, 0, false); jspTagSyntaxInfo.syntax.storeState(helpJspTagStateInfo); break; case MODE_HOST_JSPTAG_JAVA: case MODE_HOST_JAVA: javaSyntaxInfo.syntax.load(jspsi.stateOfScanningAtInit, buffer, offset, 0, false); javaSyntaxInfo.syntax.storeState(helpJavaStateInfo); break; } } else { firstTokenID = EOT; firstTokenLength = -1; } } public void loadInitState() { super.loadInitState(); nestMode = MODE_HOST; state = ISI_LANGUAGE; hostStateInfo = null; jspTagStateInfo = null; javaStateInfo = null; firstTokenID = EOT; firstTokenLength = -1; } public void load(StateInfo stateInfo, char buffer[], int offset, int len, boolean lastBuffer) { JspStateInfo jspsi = (JspStateInfo)stateInfo; if (jspsi == null) { hostStateInfo = null; jspTagStateInfo = null; javaStateInfo = null; firstTokenID = EOT; firstTokenLength = -1; } super.load(stateInfo, buffer, offset, len, lastBuffer); } public StateInfo createStateInfo() { return new JspStateInfo(); } public int compareState(StateInfo stateInfo) { if (super.compareState(stateInfo) == DIFFERENT_STATE) return DIFFERENT_STATE; JspStateInfo jspsi = (JspStateInfo)stateInfo; if (jspsi.nestMode != nestMode) return DIFFERENT_STATE; if (jspsi.isFirstTokenValid()) { if (jspsi.firstTokenID != firstTokenID) return DIFFERENT_STATE; if (jspsi.firstTokenLength != firstTokenLength) return DIFFERENT_STATE; } int ret; switch (nestMode) { case MODE_HOST: // host transferMasterToSlave(hostSyntaxInfo.syntax, hostStateInfo); ret = hostSyntaxInfo.syntax.compareState(jspsi.hostStateInfo); if (ret == DIFFERENT_STATE) return ret; if (jspsi.isFirstTokenValid()) { transferMasterToSlave(hostSyntaxInfo.syntax, helpHostStateInfo); ret = hostSyntaxInfo.syntax.compareState(jspsi.stateOfScanningAtInit); if (ret == DIFFERENT_STATE) return ret; } break; case MODE_HOST_JSPTAG: // host transferMasterToSlave(hostSyntaxInfo.syntax, hostStateInfo); ret = hostSyntaxInfo.syntax.compareState(jspsi.hostStateInfo); if (ret == Syntax.DIFFERENT_STATE) return ret; // jspTag transferMasterToSlave(jspTagSyntaxInfo.syntax, jspTagStateInfo); ret = jspTagSyntaxInfo.syntax.compareState(jspsi.jspTagStateInfo); if (ret == DIFFERENT_STATE) return ret; if (jspsi.isFirstTokenValid()) { transferMasterToSlave(jspTagSyntaxInfo.syntax, helpJspTagStateInfo); ret = jspTagSyntaxInfo.syntax.compareState(jspsi.stateOfScanningAtInit); if (ret == DIFFERENT_STATE) return ret; } break; case MODE_HOST_JSPTAG_JAVA: // host transferMasterToSlave(hostSyntaxInfo.syntax, hostStateInfo); ret = hostSyntaxInfo.syntax.compareState(jspsi.hostStateInfo); if (ret == DIFFERENT_STATE) return ret; // jspTag transferMasterToSlave(jspTagSyntaxInfo.syntax, jspTagStateInfo); ret = jspTagSyntaxInfo.syntax.compareState(jspsi.jspTagStateInfo); if (ret == DIFFERENT_STATE) return ret; // java transferMasterToSlave(javaSyntaxInfo.syntax, javaStateInfo); ret = javaSyntaxInfo.syntax.compareState(jspsi.javaStateInfo); if (ret == DIFFERENT_STATE) return ret; if (jspsi.isFirstTokenValid()) { transferMasterToSlave(javaSyntaxInfo.syntax, helpJavaStateInfo); ret = javaSyntaxInfo.syntax.compareState(jspsi.stateOfScanningAtInit); if (ret == DIFFERENT_STATE) return ret; } break; case MODE_HOST_JAVA: // host transferMasterToSlave(hostSyntaxInfo.syntax, hostStateInfo); ret = hostSyntaxInfo.syntax.compareState(jspsi.hostStateInfo); if (ret == DIFFERENT_STATE) return ret; // java transferMasterToSlave(javaSyntaxInfo.syntax, javaStateInfo); ret = javaSyntaxInfo.syntax.compareState(jspsi.javaStateInfo); if (ret == DIFFERENT_STATE) return ret; if (jspsi.isFirstTokenValid()) { transferMasterToSlave(javaSyntaxInfo.syntax, helpJavaStateInfo); ret = javaSyntaxInfo.syntax.compareState(jspsi.stateOfScanningAtInit); if (ret == DIFFERENT_STATE) return ret; } break; } return EQUAL_STATE; } public static class JspStateInfo extends BaseStateInfo { int nestMode; StateInfo hostStateInfo; StateInfo jspTagStateInfo; StateInfo javaStateInfo; /** State info for the scanning syntax at 'tokenOffset', if tokenOffset != offset (i.e. EOT was returned). */ StateInfo stateOfScanningAtInit; /** Token ID returned by the first call of the scanning slave's nextToken(), possibly EOT. */ int firstTokenID; /** Token length of the token returned by the first call of the scanning slave's nextToken(), possibly invalid. */ int firstTokenLength; public boolean isFirstTokenValid() { return (getPreScan() != 0); } public String toString(Syntax s) { //if ((getPreScan() != 0) && (stateOfScanningAtInit != null) && (stateOfScanningAtInit.getPreScan() != 0)) //new Exception("scanning prescan should be 0").printStackTrace(); return "JspStateInfo state=" + getState() + ", prescan=" + getPreScan() + ", nestMode=" + nestMode + ((getPreScan() == 0) ? "" : "\n firstTokenID=" + firstTokenID + ", firstTokenLength=" + firstTokenLength) + "\n hostStateInfo=" + (hostStateInfo == null ? "null" : ((BaseStateInfo)hostStateInfo).toString(s)) + "\n jspTagStateInfo=" + (jspTagStateInfo == null ? "null" : ((BaseStateInfo)jspTagStateInfo).toString(s)) + "\n javaStateInfo=" + (javaStateInfo == null ? "null" : ((BaseStateInfo)javaStateInfo).toString(s)) + "\n scanning Info=" + (stateOfScanningAtInit == null ? "null" : ((BaseStateInfo)stateOfScanningAtInit).toString(s)); } } } /* * Log * 5 Gandalf-post-FCS1.3.2.0 4/5/00 Petr Jiricka Token names and examples * from bundles. * 4 Gandalf 1.3 3/10/00 Petr Jiricka Debug stacktraces * removed. This fixes bug 5955, which is just a debug exception output * without any further implications. * 3 Gandalf 1.2 2/14/00 Petr Jiricka Fixed copying state * between variables. * 2 Gandalf 1.1 2/11/00 Petr Jiricka Numerous small fixes. * 1 Gandalf 1.0 2/10/00 Petr Jiricka * $ */